package com.asen.commons.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * String工具类
 *
 * @author Gary
 * @version 1.0
 * @date 2018-12-17
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {

    private static Pattern pDateTime = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1][0-9])|([2][0-4]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");

    private static Pattern pDate = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))?$");

    private static Pattern pTime = Pattern.compile("((((0?[0-9])|([1][0-9])|([2][0-4]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");


    /**
     * 指定字符串出现次数
     *
     * @param srcStr
     * @param findStr
     * @return
     */
    public static int count(String srcStr, String findStr) {
        int count = 0;
        int index = 0;

        while ((index = srcStr.indexOf(findStr, index)) != -1) {
            index = index + findStr.length();
            count++;

        }

        return count;
    }

    public static boolean notEquals(final CharSequence cs1, final CharSequence cs2) {
        return !equals(cs1, cs2);
    }

    public static String toString(Object o) {
        if (o == null) {
            return null;
        }

        if (o instanceof String) {
            return (String) o;
        }

        if (o instanceof BigDecimal) {
            return ((BigDecimal) o).stripTrailingZeros().toPlainString();
        }

        if (o instanceof Date) {
            return DateUtil.parseDateToString((Date) o, DateUtil.FORMAT1);
        }

        return o.toString();
    }


    public static Integer toInteger(Object o) {
        if (o == null) {
            return null;
        }

        if (o instanceof Integer) {
            return ((Integer) o);
        }

        return Integer.valueOf(o.toString());
    }

    public static String toSureString(Object o) {
        if (o == null) {
            return "";
        }

        if (o instanceof BigDecimal) {
            return ((BigDecimal) o).stripTrailingZeros().toPlainString();
        }

        return o.toString();
    }

    /**
     * 字符串截取,中文算二个长度
     *
     * @param str
     * @param length
     * @return
     */
    public static String getSubString(String str, int length) {
        if (str == null) {
            return str;
        }
        if (str.length() < (length / 2)) {
            return str;
        }
        int count = 0;
        int offset = 0;
        char[] c = str.toCharArray();
        int size = c.length;
        if (size >= length) {
            for (int i = 0; i < c.length; i++) {
                if (c[i] > 256) {
                    offset = 2;
                    count += 2;
                } else {
                    offset = 1;
                    count++;
                }
                if (count == length) {
                    return str.substring(0, i + 1);
                }
                if ((count == length + 1 && offset == 2)) {
                    return str.substring(0, i);
                }
            }
        } else {
            return str;
        }
        return "";
    }

    /**
     * 下划线转驼峰
     *
     * @param para
     * @return
     */
    public static String underlineToHump(String para) {
        StringBuilder result = new StringBuilder();
        String[] a = para.split("_");
        for (String s : a) {
            if (result.length() == 0) {
                result.append(s.toLowerCase());
            } else {
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

    /***
     * 驼峰命名转为下划线命名
     *
     * @param para
     *        驼峰命名的字符串
     */

    public static String humpToUnderline(String para) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < para.length(); i++) {
            if (Character.isUpperCase(para.charAt(i))) {
                sb.append("_" + Character.toLowerCase(para.charAt(i)));
            } else {
                sb.append(para.charAt(i));
            }

        }
        return sb.toString();
    }

    /***
     * 驼峰命名转为横杠线命名
     *
     * @param para
     *        驼峰命名的字符串
     */

    public static String humpToDashLine(String para) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < para.length(); i++) {
            if (Character.isUpperCase(para.charAt(i))) {
                sb.append("-" + Character.toLowerCase(para.charAt(i)));
            } else {
                sb.append(para.charAt(i));
            }

        }
        return sb.toString();
    }

    /**
     * 首字母转小写
     *
     * @param s
     * @return
     */
    public static String firstAlpha2LowerCase(String s) {
        if (s == null) {
            return null;
        }

        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

    /**
     * 首字母转大写
     *
     * @param s
     * @return
     */
    public static String firstAlpha2UpperCase(String s) {
        if (s == null) {
            return null;
        }

        if (Character.isUpperCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

    /**
     * 获取最后一个单词
     *
     * @param s
     * @return
     */
    public static String getLastWord(String s) {
        if (s == null) {
            return null;
        }

        int index = 0;
        char[] chars = s.toCharArray();
        for (int i = chars.length - 1; i >= 0; i--) {
            if (Character.isUpperCase(chars[i])) {
                index = i;
                break;
            }
        }

        return firstAlpha2LowerCase(s.substring(index));
    }

    /**
     * 去掉最后一个单词
     *
     * @param s
     * @return
     */
    public static String removeLastWord(String s) {
        if (s == null) {
            return null;
        }

        int index = 0;
        char[] chars = s.toCharArray();
        for (int i = chars.length - 1; i >= 0; i--) {
            if (Character.isUpperCase(chars[i])) {
                index = i;
                break;
            }
        }

        return s.substring(0, index);
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     *
     * @param datetime
     * @return
     */
    public static boolean isDateTime(String datetime) {
        return pDateTime.matcher(datetime).matches();
    }

    /**
     * yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static boolean isDate(String date) {
        return pDate.matcher(date).matches();
    }

    /**
     * HH:mm:ss
     *
     * @param time
     * @return
     */
    public static boolean isTime(String time) {
        return pTime.matcher(time).matches();
    }

    public static boolean emp(String str) {
        boolean blank = org.apache.commons.lang3.StringUtils.isBlank(str);
        return (blank || "null".equals(str) || "NULL".equals(str));
    }

    public static boolean notEmp(String str) {
        return !emp(str);
    }

    public static String sure(Object str) {
        if (str == null) {
            return "";
        }
        return toString(str);
    }

    public static String collToString(Collection<?> collection, String splitStr) {
        if (CollectionUtils.isEmpty(collection)) {
            return "";
        }
        int index = 0;
        int size = collection.size();
        StringBuffer stringBuffer = new StringBuffer();
        for (Object o : collection) {
            if (index == size - 1) {
                stringBuffer.append(toString(o));
            } else {
                stringBuffer.append(toString(o)).append(splitStr);
            }
            index++;
        }
        return stringBuffer.toString();
    }

    /**
     * 将两个用某个字符拼接的字符串去重重新拼接
     *
     * @param str1
     * @param str2
     * @return
     */
    public static String megerArrStr(String str1, String str2) {
        return megerArrStr(str1, str2, ",");
    }

    /**
     * 将两个用某个字符拼接的字符串去重重新拼接
     *
     * @param str1
     * @param str2
     * @param split
     * @return
     */
    public static String megerArrStr(String str1, String str2, String split) {
        if (isBlank(str1)) {
            return str2;
        }
        if (isBlank(str2)) {
            return str1;
        }
        Set<String> stringSet = new HashSet<>();
        stringSet.addAll(Arrays.asList(str1.split(split)));
        stringSet.addAll(Arrays.asList(str2.split(split)));
        return join(stringSet, split);
    }

    /**
     * 查找字符串中，两个特殊字符中的字符串
     *
     * @param str     整体长字符串
     * @param fromStr 开始字符串
     * @param endStr  结束字符串
     * @return
     */
    public static String strBetween(String str, String fromStr, String endStr) {
        String pattern = "(?<=" + fromStr + ").*?(?=" + endStr + ")";

        // 创建 Pattern 对象
        Pattern r = Pattern.compile(pattern);
        // 现在创建 matcher 对象
        Matcher m = r.matcher(str);
        if (m.find()) {
            return m.group();
        } else {
            return null;
        }
    }

    /**
     * 去掉字符串中的运算符号
     *
     * @param str
     * @return
     */
    public static String strExcepteSymbol(String str) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        str = str.trim();
        String[] endCharArray = {",", "\\+", "\\-", "\\*", "\\/", "\\=", "\\)"};
        for (int i = 0; i < endCharArray.length; i++) {
            str = str.replace(endCharArray[i], "");
        }
        return str;
    }

    public static String excludeStringParam(String str) {
        if (str.indexOf("\"") >= 0) {
            String content = strBetween(str, "\"", "\"");
            str = str.replace("\"" + content + "\"", "字符串占位");
            return excludeStringParam(str);
        }

        return str;
    }

    /**
     * 去除字符串前后双引号
     *
     * @param obj
     * @return
     */
    public static String trimMarks(Object obj) {
        String str = sure(obj);
        if (isBlank(str)) {
            return str;
        }
        if (str.indexOf("\"") == 0 && str.endsWith("\"")) {
            return str.substring(1, str.length() - 1);
        }
        return str;
    }

    public static Long toLong(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Long) {
            return (Long) obj;
        }
        try {
            return Long.valueOf(obj.toString());
        } catch (Exception e) {
            return null;
        }
    }

    public static BigDecimal toDecimal(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof BigDecimal) {
            return (BigDecimal) obj;
        }
        if (obj instanceof Number) {
            return new BigDecimal(((Number) obj).doubleValue());
        }
        try {
            return new BigDecimal(obj.toString());
        } catch (Exception e) {
            return null;
        }
    }

    public static Boolean toBool(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof Boolean) {
            return (Boolean) obj;
        }
        try {
            return Boolean.valueOf(obj.toString());
        } catch (Exception e) {
            return null;
        }
    }

    public static List<String> readLines(String s) throws IOException {
        List<String> list = new ArrayList<>();
        if (isEmpty(s)) {
            return list;
        }
        BufferedReader reader = new BufferedReader(new StringReader(s));
        String line;
        while ((line = reader.readLine()) != null) {
            list.add(line);
        }
        return list;
    }

    public static String setMaxLength(String s, int maxLength) {
        return isNotEmpty(s) && s.length() > maxLength ? s.substring(0, maxLength) : s;
    }


    /**
     * 把中文带有括号的字符串转化为全角括号
     * 把非中文带有括号的字符串转化为半角括号
     *
     * @param s 字符串
     * @return 替换后的字符
     */
    public static String toBcCase(String s) {
        if (isEmpty(s)) {
            return null;
        }
        boolean isCN = isChinese(s);
        Set<Character> convertSet = new HashSet<>();
        if (isCN) {
            convertSet.add('(');
            convertSet.add(')');
            s = toSBC(s, convertSet, null);
        } else {
            convertSet.add('（');
            convertSet.add('）');
            s = toDBC(s, convertSet, null);
        }
        return s;
    }

    // 判断一个字符串是否含有中文
    public static boolean isChinese(String str) {
        if (str == null) return false;
        for (char c : str.toCharArray()) {
            if (isChinese(c)) return true;// 有一个中文字符就返回
        }
        return false;
    }

    public static boolean isChinese(char c) {
        return c >= 0x4E00 && c <= 0x9FA5;// 根据字节码判断
    }

    /**
     * 半角转全角
     *
     * @param input         String
     * @param convertSet    指定替换的字符集合
     * @param notConvertSet 不替换的字符集合
     * @return 全角字符串.
     */
    public static String toSBC(String input, Set<Character> convertSet, Set<Character> notConvertSet) {
        char c[] = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (null != notConvertSet && notConvertSet.contains(c[i])) {
                // 跳过不替换的字符
                continue;
            }
            if (null != convertSet && convertSet.contains(c[i])) {
                if (c[i] == ' ') {
                    c[i] = '\u3000';
                } else if (c[i] < '\177') {
                    c[i] = (char) (c[i] + 65248);

                }
            }
        }
        return new String(c);
    }

    /**
     * 替换全角为半角
     *
     * @param text          文本
     * @param convertSet    指定替换的字符集合
     * @param notConvertSet 不替换的字符集合
     * @return 替换后的字符
     */
    public static String toDBC(String text, Set<Character> convertSet, Set<Character> notConvertSet) {
        char c[] = text.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (null != notConvertSet && notConvertSet.contains(c[i])) {
                // 跳过不替换的字符
                continue;
            }
            if (null != convertSet && convertSet.contains(c[i])) {
                if (c[i] == '\u3000') {
                    c[i] = ' ';
                } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
                    c[i] = (char) (c[i] - 65248);
                }
            }
        }
        String returnString = new String(c);

        return returnString;
    }

    public static void acceptIfNotBlank(String text, Consumer<String> task) {
        if (StringUtils.isNotBlank(text)) {
            task.accept(text);
        }
    }

    public static void acceptIfBlank(String text, Consumer<String> task) {
        if (StringUtils.isBlank(text)) {
            task.accept(text);
        }
    }
}
